package cn.usbtg.session.impl;

import cn.usbtg.core.exception.BTGRuntimeException;
import cn.usbtg.session.BTGSession;
import cn.usbtg.session.BTGSessionDao;
import cn.usbtg.sutil.EmptyUtil;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;

import java.util.Hashtable;

/**
 * 基于redis的session存储实现
 */
public class BTGRedisSessionDao implements BTGSessionDao {
    private String redisName;
    private Cache sessionCache; //redis session cache

    public BTGRedisSessionDao() {
        this.sessionCache = Redis.use();
    }

    public BTGRedisSessionDao(String redisName) {
        if (EmptyUtil.isEmpty(redisName)) {
            throw new BTGRuntimeException("session cache is null");
        }
        this.redisName = redisName;
        this.sessionCache = Redis.use(redisName);
    }

    /**
     * 获取验证过sessionCache对象
     *
     * @return Cache
     */
    private Cache getCheckedSessionCache() {
        if (EmptyUtil.isEmpty(this.sessionCache)) {
            throw new BTGRuntimeException("sessionCache " + (EmptyUtil.isEmpty(this.redisName) ? "default" : this.redisName) + " is null");
        }
        return this.sessionCache;
    }

    @Override
    public void saveSession(BTGSession session) {
        if (EmptyUtil.isEmpty(session)) {
            throw new BTGRuntimeException("session is null");
        }
        if (session.getMaxInactiveInterval() < 1000) {
            throw new BTGRuntimeException("session.maxInactiveInterval must be greater than 1000(1s)");
        }
        this.getCheckedSessionCache().setex(session.getId(), session.getMaxInactiveInterval() / 1000, session);
    }

    @Override
    public void deleteSession(String sessionId) {
        if (EmptyUtil.isEmpty(sessionId)) {
            throw new BTGRuntimeException("session id is null");
        }
        this.getCheckedSessionCache().del(sessionId);
    }

    @Override
    public BTGSession getSession(String sessionId) {
        return this.getCheckedSessionCache().get(sessionId);
    }

    @Override
    public void refreshSession(BTGSession session) {
        if (EmptyUtil.isEmpty(session)) {
            throw new BTGRuntimeException("session is null");
        }
        //重新保存该session即可覆盖原有session
        this.saveSession(session);
    }

    @Override
    public void active(BTGSession session) {
        this.getCheckedSessionCache().expire(session.getId(), session.getMaxInactiveInterval() / 1000);
    }

    @Override
    public Hashtable<String, BTGSession> getSessions() {
        Hashtable<String, BTGSession> sessions = new Hashtable<>();
        for (String key : this.getCheckedSessionCache().keys("*")) {
            Object osession = this.getCheckedSessionCache().get(key);
            if (EmptyUtil.isNotEmpty(osession)) {
                sessions.put(key, (BTGSession) osession);
            }
        }
        return sessions;
    }

    @Override
    public void clearTimeout() {
        //redis会自动管理过期删除，所以此处无需自己写实现
        //for (BTGSession session : this.getSessions().values()) {
        //    if (session.isInvalidate()) {
        //        deleteSession(session.getId());
        //    }
        //}
    }

    @Override
    public void clear() {
        this.getCheckedSessionCache().getJedis().flushDB();
    }
}